home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- glo_obj.c - Code to support GL based 3D objects.
-
- Tim Heidmann, Silicon Graphics
- Created Oct 5, 1988
- Last Edit July 22, 1991
- */
-
- #include <stdio.h>
- #include <gl.h>
- #include "glo_obj.h"
-
- /* A cube:
- 5----6
- |\ |\
- | 1----2
- | | | |
- 4-|--7 |
- \| \|
- 0----3
- */
- int cube_list[] = {
- NPERP,
- BGNPOLY, 8, 4, 5, 6, 7, ENDPOLY, /* Back */
- BGNPOLY, 9, 3, 2, 1, 0, ENDPOLY, /* Front */
- BGNPOLY, 10, 0, 4, 7, 3, ENDPOLY, /* Bottom */
- BGNPOLY, 11, 1, 2, 6, 5, ENDPOLY, /* Top */
- BGNPOLY, 12, 0, 1, 5, 4, ENDPOLY, /* Left */
- BGNPOLY, 13, 2, 3, 7, 6, ENDPOLY, /* Right */
- ENDLIST
- };
- float cube_t[][3] = {
- -0.5, -0.5, 0.5, /* 0 - Front Face */
- -0.5, 0.5, 0.5, /* 1 */
- 0.5, 0.5, 0.5, /* 2 */
- 0.5, -0.5, 0.5, /* 3 */
- -0.5, -0.5, -0.5, /* 4 - Back Face */
- -0.5, 0.5, -0.5, /* 5 */
- 0.5, 0.5, -0.5, /* 6 */
- 0.5, -0.5, -0.5, /* 7 */
- 0.0, 0.0, -1.0, /* 8 - Back Normal */
- 0.0, 0.0, 1.0, /* 9 - Front Normal */
- 0.0, -1.0, 0.0, /* 10 - Bottom Normal */
- 0.0, 1.0, 0.0, /* 11 - Top Normal */
- -1.0, 0.0, 0.0, /* 12 - Left Normal */
- 1.0, 0.0, 0.0 /* 13 - Right Normal */
- };
- glo_ObjTyp glo_cube = {cube_list, cube_t};
-
- struct glo_lnl {
- int cmd;
- char *name;
- } glo_ListNameList[] = {
- {ENDLIST, "ENDLIST"},
- {BGNTMSH, "BGNTMSH"},
- {ENDTMSH, "ENDTMSH"},
- {SWAPTMSH, "SWAPTMSH"},
- {BGNPOLY, "BGNPOLY"},
- {ENDPOLY, "ENDPOLY"},
- {BGNLINE, "BGNLINE"},
- {ENDLINE, "ENDLINE"},
- {NPERV, "NPERV"},
- {NPERP, "NPERP"},
- {NONORM, "NONORM"}
- };
- int glo_ListNameListLen = (sizeof(glo_ListNameList)/sizeof(struct glo_lnl));
-
- /* Useful function prototypes */
- char *
- glo_ListName(int listItem);
- int
- glo_ParseCmd(char name[]);
- Boolean
- glo_FileLine(FILE *fd, char buffer[]);
-
-
- void
- glo_DrawObj(glo_ObjPtr glop)
- {
- int *lip, mode;
-
- if (glop == NULL) return;
-
- mode = NONORM;
- lip = glop->list;
- for (;;) {
- switch (*lip++) {
- case ENDLIST: return;
- case NPERP: mode = NPERP; break;
- case NPERV: mode = NPERV; break;
- case NONORM: mode = NONORM; break;
- case BGNPOLY: bgnpolygon();
- switch (mode) {
- case NPERP: /* Normal per polygon */
- if (*lip < 0) break;
- n3f(glop->t + *lip++);
- for (;;) {
- if (*lip < 0) break;
- v3f(glop->t + *lip++);
- }
- break;
- case NPERV: /* Normal per vertex */
- for (;;) {
- if (*lip < 0) break;
- n3f(glop->t + *lip++);
- v3f(glop->t + *lip++);
- }
- break;
- case NONORM: /* No Normals */
- for (;;) {
- if (*lip < 0) break;
- v3f(glop->t + *lip++);
- }
- break;
- default: ; }
- break;
-
- case ENDPOLY: endpolygon(); break;
- default:
- if (lip[-1] >= USEMATL && lip[-1] < 0) {
- lmbind(MATERIAL, lip[-1] - USEMATL);
- }
- break;
- }
- }
- }
-
-
- void
- glo_DrawGeometry(glo_ObjPtr glop)
- {
- /* Draw the object - geometry only, no lmbind()'s or n3f()'s */
- int *lip, mode;
-
- if (glop == NULL) return;
-
- mode = NONORM;
- lip = glop->list;
- for (;;) {
- switch (*lip++) {
- case ENDLIST: return;
- case NPERP: mode = NPERP; break;
- case NPERV: mode = NPERV; break;
- case NONORM: mode = NONORM; break;
- case BGNPOLY: bgnpolygon();
- switch (mode) {
- case NPERP: /* Normal per polygon */
- if (*lip < 0) break;
- lip++; /* Skip the normal */
- for (;;) {
- if (*lip < 0) break;
- v3f(glop->t + *lip++);
- }
- break;
- case NPERV: /* Normal per vertex */
- for (;;) {
- if (*lip < 0) break;
- lip++; /* Skip the normal */
- v3f(glop->t + *lip++);
- }
- break;
- case NONORM: /* No Normals */
- for (;;) {
- if (*lip < 0) break;
- v3f(glop->t + *lip++);
- }
- break;
- default: ; }
- break;
-
- case ENDPOLY: endpolygon(); break;
- default:
- /* Ignore material changes */
- break;
- }
- }
- }
-
-
- void
- glo_DrawNormals(glo_ObjPtr glop)
- {
- /* Draw just the normals as yellow vectors */
- int *lip, mode;
- float lastNormal[3];
-
- if (glop == NULL) return;
-
- mode = NONORM;
- lip = glop->list;
- for (;;) {
- switch (*lip++) {
- case ENDLIST: return;
- case NPERP: mode = NPERP; break;
- case NPERV: mode = NPERV; break;
- case NONORM: mode = NONORM; break;
- case BGNPOLY:
- cpack(0xff00ffff);
- switch (mode) {
- case NPERP: /* Normal per polygon */
- if (*lip < 0) break;
- vcopy(glop->t + *lip++, lastNormal);
- bgnline();
- v3f(glop->t + *lip);
- vadd(glop->t + *lip++, lastNormal, lastNormal);
- v3f(lastNormal);
- endline();
- for (;;) {
- if (*lip++ < 0) break;
- }
- break;
- case NPERV: /* Normal per vertex */
- for (;;) {
- if (*lip < 0) break;
- vcopy(glop->t + *lip++, lastNormal);
- bgnline();
- v3f(glop->t + *lip);
- vadd(glop->t + *lip++, lastNormal, lastNormal);
- v3f(lastNormal);
- endline();
- }
- break;
- case NONORM: /* No Normals */
- for (;;) {
- if (*lip++ < 0) break;
- }
- break;
- default: ; }
- break;
-
- case ENDPOLY:
- break;
- default:
- break;
- }
- }
- }
-
- glo_ObjPtr
- glo_NewObj(int nList, int nTriplets) {
- glo_ObjPtr myObj;
-
- myObj = (glo_ObjPtr) malloc(sizeof(glo_ObjTyp));
- myObj->list = (int *) malloc(sizeof(int) * nList);
- myObj->t = (float (*)[3]) malloc(sizeof(float) * 3 * nTriplets);
- myObj->list[0] = ENDLIST;
- return myObj;
- }
-
-
- glo_ObjPtr
- glo_ReadObj(char filename[]) {
- int i, j, iList, iTrip, nList, nTriplets, count, maxRef;
- FILE *inf;
- glo_ObjPtr myObj;
- int *pList, l[16];
- float *pTriplet, fileVersion;
- char buf[256], cmd[60], fileType[60];
-
- if ((inf = fopen(filename, "r")) == NULL) {
- fprintf(stderr, "Cannot open file %s for reading.\n", filename);
- return NULL;
- }
-
- /* Check file type. Allocate space for lists. */
- if (!glo_FileLine(inf, buf)) return NULL;
- if (sscanf(buf,"%s %f", fileType, &fileVersion) != 2 ||
- strcmp(fileType, "glo_obj") != 0) {
- /*
- fprintf(stderr, "File %s is not a glo_obj file.\n", filename);
- */
- return NULL;
- }
- if (!glo_FileLine(inf, buf)) {
- fprintf(stderr, "Unexpected end of glo_obj file %s\n", filename);
- return NULL;
- }
- sscanf(buf, "%d %d", &nList, &nTriplets);
- myObj = glo_NewObj(nList, nTriplets);
-
- /* Read the command list */
- maxRef = -1;
- for (pList=myObj->list, iList=0; iList<nList; pList++, iList++) {
- if (!glo_FileLine(inf, buf)) {
- fprintf(stderr, "Unexpected end of glo_obj file %s\n", filename);
- goto bail;
- }
- sscanf(buf, "%s", cmd);
- if (cmd[0]>='0' && cmd[0]<='9') {
- /* Read a list of indices */
- count = sscanf(buf,
- "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
- l, l+1, l+2, l+3, l+4, l+5, l+6, l+7, l+8, l+9,
- l+10, l+11, l+12, l+13, l+14, l+15);
- for (j=0; j<count; j++) {
- pList[j] = l[j];
- if (l[j] > maxRef) maxRef = l[j];
- }
- pList += j-1;
- iList += j-1;
- }
- else {
- /* Read and parse a command */
- if (strcmp(cmd, "USEMATL")==0) {
- /* Parse a USEMATL <matl #> command */
- sscanf(buf, "%*s %d", &i);
- *pList = USEMATL+i;
- }
- else {
- /* Find a simple command */
- if ((*pList = glo_ParseCmd(cmd)) == 0) {
- fprintf(stderr, "Unknown keyword: %s\n", cmd);
- goto bail;
- }
- if (*pList == ENDLIST) break;
- }
- }
- }
-
- /* Read the triplet list */
- for (iTrip=0, pTriplet= *myObj->t; iTrip<nTriplets; iTrip++, pTriplet+=3) {
- if (!glo_FileLine(inf, buf) && iTrip <= maxRef) {
- fprintf(stderr, "Unexpected end of glo_obj file %s\n", filename);
- goto bail;
- }
- sscanf(buf, "%f %f %f", pTriplet, pTriplet+1, pTriplet+2);
- }
-
- /* Finish up */
- fclose(inf);
- return myObj;
-
-
- /* Free allocated memory and return failure */
- bail:
- free(myObj->list);
- free(myObj->t);
- free(myObj);
- return NULL;
- }
-
- void
- glo_WriteObj(glo_ObjPtr theObj, char filename[]) {
- int i, nList, nTriplets, iVerts;
- FILE *outf;
- int *pList;
- float (*tList)[3];
-
- if ((outf = fopen(filename, "w")) == NULL) {
- fprintf(stderr, "Cannot open file %s for writing.\n", filename);
- /* 3/25/93 ratman--trying to make compile on sherwood
- return FALSE;
- */
- exit(-1);
- }
-
- /* Write the header: File type and Version,
- then command list and triplet array lengths */
- fprintf(outf, "glo_obj 1.0\n");
- glo_GetLengths(theObj, &nList, &nTriplets);
- fprintf(outf, "%d %d\n", nList, nTriplets);
-
- /* Write the command list */
- for (pList = theObj->list;;)
- if (*pList < 0) {
- if (*pList >= USEMATL)
- fprintf(outf, "USEMATL %d\n", *pList - USEMATL);
- else
- fprintf(outf, "%s\n", glo_ListName(*pList));
- if (*pList == ENDLIST) break;
- pList++;
- } else {
- for (iVerts=0; *pList >= 0; pList++, iVerts++) {
- if (iVerts >= 16) {
- /* Keep the output to 16 indices per line */
- fprintf(outf, "\n");
- iVerts = 0;
- }
- fprintf(outf, " %d", *pList);
- }
- fprintf(outf, "\n");
- }
-
- /* Write the triplet list */
- for (i=0, tList=theObj->t; i<nTriplets; i++,tList++)
- fprintf(outf, "%12.6f %12.6f %12.6f\n",
- (*tList)[0], (*tList)[1], (*tList)[2]);
-
- /* Finish up */
- fclose(outf);
- /* 3/25/93 ratman--trying to make compile on sherwood
- return TRUE;
- */
- }
-
- void
- glo_GetLengths(glo_ObjPtr theObj, int *listLen, int *tripletLen) {
- /* Return length of command and triplet lists,
- based on the appearance of ENDLIST,
- and the highest referenced triplet index. */
- int i, highestTriplet;
-
- highestTriplet = -1;
- for (i=0; theObj->list[i] != ENDLIST; i++)
- if (theObj->list[i] > highestTriplet)
- highestTriplet = theObj->list[i];
- *listLen = i + 1;
- *tripletLen = highestTriplet + 1;
- }
-
- char *
- glo_ListName(int listItem) {
- int i;
- for (i=0; i<glo_ListNameListLen; i++)
- if (listItem == glo_ListNameList[i].cmd)
- return glo_ListNameList[i].name;
- return NULL;
- }
-
- int
- glo_ParseCmd(char name[]) {
- int i;
- for (i=0; i<glo_ListNameListLen; i++)
- if (strcmp(name, glo_ListNameList[i].name)==0)
- return glo_ListNameList[i].cmd;
- return 0;
- }
-
- Boolean
- glo_FileLine(FILE *fd, char buffer[]) {
- /* Read a line from fd, skipping over comments */
- do
- if (fgets(buffer, 256, fd) == NULL) return FALSE;
- while (buffer[0] == '#');
- return TRUE;
- }
-
-